package main

import (
	"database/sql"
	"log"
	"net/http"
	"text/template"
	_ "github.com/go-sql-driver/mysql"
	"fmt"
	"regexp"
)

type Users struct {
	Id    int
	Name  string
	Email string
}

//定义一个实现Handler接口
type Handler interface {
	ServeHTTP(http.ResponseWriter,*http.Request)
}

//声明一个结构体
type MyMux struct {
	routers map[string]func(http.ResponseWriter, *http.Request)
}

//实现ServeHTTP方法
func (p *MyMux) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	//遍历routers,寻找匹配的path
	for path, f := range p.routers {
		if ok, _ :=regexp.MatchString("^" + path + "$", r.URL.Path); ok {
			f(w, r)
			return
		}
	}
	fmt.Fprintf(w, "Error: Dont't match URL '%s'", r.URL.Path)

}

//定义一个静态文件资源
func Static(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Deal Static: ", r.URL.Path)
	w.Header().Set("Content-Type", "text/css")
	http.ServeFile(w, r, "." + r.URL.Path)
}

//创建数据库连接
func dbConn() (db *sql.DB) {
	//dbDriver := "mysql"
	//dbUser := "dba"
	//dbPass := "123456"
	//dbName := "test"
	db, err := sql.Open("mysql", "dba:123456@tcp(10.0.10.110:3306)/goblog?charset=utf8")

	if err != nil {
		panic(err)
	}
	return db
}

//定义模版文件的绝对路径，就是在html下
var tmpl = template.Must(template.ParseGlob("html/*"))

func Index(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	selDB, err := db.Query("SELECT * FROM users ORDER BY id DESC")
	if err != nil {
		panic(err.Error())
	}
	emp := Users{}
	res := []Users{}
	for selDB.Next() {
		var id int
		var name, email string
		err = selDB.Scan(&id, &name, &email)
		if err != nil {
			panic(err.Error())
		}
		emp.Id = id
		emp.Name = name
		emp.Email = email
		res = append(res, emp)
	}
	tmpl.ExecuteTemplate(w, "Index", res)
	defer db.Close()
}

func Show(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	nId := r.URL.Query().Get("id")
	selDB, err := db.Query("SELECT * FROM users WHERE id=?", nId)
	if err != nil {
		panic(err.Error())
	}
	emp := Users{}
	for selDB.Next() {
		var id int
		var name, email string
		err = selDB.Scan(&id, &name, &email)
		if err != nil {
			panic(err.Error())
		}
		emp.Id = id
		emp.Name = name
		emp.Email = email
	}
	tmpl.ExecuteTemplate(w, "Show", emp)
	defer db.Close()
}

func New(w http.ResponseWriter, r *http.Request) {
	tmpl.ExecuteTemplate(w, "New", nil)
}

func Edit(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	nId := r.URL.Query().Get("id")
	selDB, err := db.Query("SELECT * FROM users WHERE id=?", nId)
	if err != nil {
		panic(err.Error())
	}
	emp := Users{}
	for selDB.Next() {
		var id int
		var name, email string
		err = selDB.Scan(&id, &name, &email)
		if err != nil {
			panic(err.Error())
		}
		emp.Id = id
		emp.Name = name
		emp.Email = email
	}
	tmpl.ExecuteTemplate(w, "Edit", emp)
	defer db.Close()
}

func Insert(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	if r.Method == "POST" {
		name := r.FormValue("name")
		email := r.FormValue("email")
		insForm, err := db.Prepare("INSERT INTO users(name, email) VALUES(?,?)")
		if err != nil {
			panic(err.Error())
		}
		insForm.Exec(name, email)
		log.Println("INSERT: Name: " + name + " | Email: " + email)
	}
	defer db.Close()
	http.Redirect(w, r, "/", 301)
}

func Update(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	if r.Method == "POST" {
		name := r.FormValue("name")
		email := r.FormValue("email")
		id := r.FormValue("uid")
		insForm, err := db.Prepare("UPDATE users SET name=?, email=? WHERE id=?")
		if err != nil {
			panic(err.Error())
		}
		insForm.Exec(name, email, id)
		log.Println("UPDATE: Name: " + name + " | Email: " + email)
	}
	defer db.Close()
	http.Redirect(w, r, "/", 301)
}

func Delete(w http.ResponseWriter, r *http.Request) {
	db := dbConn()
	emp := r.URL.Query().Get("id")
	delForm, err := db.Prepare("DELETE FROM users WHERE id=?")
	if err != nil {
		panic(err.Error())
	}
	delForm.Exec(emp)
	log.Println("DELETE user" + emp)
	defer db.Close()
	http.Redirect(w, r, "/", 301)
}

func main() {
	mux := &MyMux{}
	mux.routers = make(map[string]func(http.ResponseWriter, *http.Request))
	log.Println("Server started on: http://localhost:8088")
	mux.routers["/static/.+"] = Static
	mux.routers["/"] = Index
	mux.routers["/show"] = Show
	mux.routers["/new"] = New
	mux.routers["/edit"] = Edit
	mux.routers["/insert"] = Insert
	mux.routers["/update"] = Update
	mux.routers["/delete"] = Delete
	//http.HandleFunc("/", Index)
	//http.HandleFunc("/show", Show)
	//http.HandleFunc("/new", New)
	//http.HandleFunc("/edit", Edit)
	//http.HandleFunc("/insert", Insert)
	//http.HandleFunc("/update", Update)
	//http.HandleFunc("/delete", Delete)
	err := http.ListenAndServe(":8088", mux)
	//http.ListenAndServe(":8088", nil)
	if err != nil {
		log.Println("Error: ", err)
	}
}
